
#include <BFont>
#include <BPainter>
#include <BFocusEvent>
#include <BMouseEvent>
#include <BKeyEvent>

#include "IComboBoard.h"
#include "member_BComboBox.h"

using namespace BWE;

IComboBoard::IComboBoard(member_BComboBox& com_member, BComboBox* parent) : member(com_member), BWidget(parent)
{
	combox = parent;
	hoveredIndex = -1;
	pressedIndex = -1;
	vScrollBar = new BScrollBar(this);
	vScrollBar->hide();
}
IComboBoard::~IComboBoard()
{

}

void IComboBoard::freshItemRects()
{
	const BFont* font = this->font();
	if (!font)
		return;
	int cx = this->clientRect().x();
	int cy = this->clientRect().y();
	int cw = this->clientRect().width();
	int ch = this->clientRect().height();

	int posY = cy;
	for (int i = 0; i < member.items.size(); i++)
	{
		ComboItem& item = member.items[i];
		item.rect.set(cx, posY, cw, member.rowHeight);
		item.iconRect = item.rect.align(member.align, member.iconSize);
		item.textSize = font->textSize(item.text);
		BRect textArea = item.rect;
		if (member.align & Align_Left)
			textArea.left() = item.iconRect.right() + member.space;
		if (member.align & Align_Right)
			textArea.right() = item.iconRect.left() - member.space;
		item.textRect = textArea.align(member.align, item.textSize);
		posY += member.rowHeight;
	}
	totalSize.set(cw, posY);
}
void IComboBoard::focusEvent(const BFocusEvent& focusEvent)
{
	if (focusEvent.focus() == Focus_In)
	{

	}
	if (focusEvent.focus() == Focus_Out)
	{
		this->hide();
	}
}
void IComboBoard::keyDownEvent(const BKeyEvent& keyEvent)
{
	if (keyEvent.key() == Key_Enter)
	{
		combox->setCurrent(hoveredIndex);
		this->hide();
		return;
	}

	int index = hoveredIndex;
	if(keyEvent.key() == Key_Up)
		index--;
	if(keyEvent.key() == Key_Down)
		index++;
	member.items.correct(index);
	if (hoveredIndex != index)
	{
		hoveredIndex = index;
		fresh();
	}
}

void IComboBoard::showEvent(const BEvent& showEvent)
{
	int x = 0;
	int y = combox->height();
	int w = combox->width();
	int h = (member.rowHeight + 1) * member.items.size() ;
	this->setRect(x, y, w, h);
	freshItemRects();
}

void IComboBoard::paintEvent(const BEvent& event)
{
	BWidget::paintEvent(event);

	int width = this->width();
	int height = this->height();

	BPainter painter(this);

	for(int i = 0; i < member.items.size(); i++)
	{
		ComboItem& item = member.items[i];
		const BRect& rect = item.rect;

		State state = State_Normal;
		if (combox_member(combox)->current == i)
		{
			painter.setColor(Color_Item_Selected);
			painter.fillRect(rect);
			painter.setColor(Value_Border);
			painter.drawRect(rect);
			state = State_Pressed;
		}
		if(hoveredIndex == i)
		{
			painter.setColor(Color_Item_Hovered);
			painter.fillRect(rect);
			painter.setColor(Value_Border);
			painter.drawRect(rect);
			state = State_Hovered;
		}
		if (item.icon)
		{
			painter.drawImage(item.iconRect, item.icon->image(state));
		}
		painter.setColor(Color_Text);
		painter.drawText(item.textRect, item.text);
	}
}

void IComboBoard::mouseEnterEvent(const BMouseEvent& mouseEvent)
{
	pressedIndex = -1;
	hoveredIndex = -1;
}
void IComboBoard::mouseLeaveEvent(const BMouseEvent& mouseEvent)
{
	pressedIndex = -1;
	hoveredIndex = -1;
}

void IComboBoard::mouseClickEvent(const BMouseEvent& mouseEvent)
{
	const BPoint& pos = mouseEvent.pos();
	for(int i = 0; i < member.items.size(); i++)
	{
		ComboItem& item = member.items[i];
		if(item.rect.contain(pos))
		{
			combox->setCurrent(i);
			combox->emit(Signal_CurrentSelected, i);
			this->hide();
			break;
		}
	}
}
void IComboBoard::mouseMoveEvent(const BMouseEvent& mouseEvent)
{
	const BPoint& pos = mouseEvent.pos();
	for(int i = 0; i < member.items.size(); i++)
	{
		ComboItem& item = member.items[i];
		if(item.rect.contain(pos))
		{
			if(hoveredIndex != i)
			{
				hoveredIndex = i;
				combox->emit(Signal_ItemHovered, hoveredIndex);
				fresh();
			}
			break;
		}
	}
}
void IComboBoard::mouseWheelEvent(const BMouseEvent& mouseEvent)
{
	int temp = hoveredIndex;
	if (mouseEvent.wheel() > 0)
		hoveredIndex++;
	if (mouseEvent.wheel() < 0)
		hoveredIndex--;
	if (hoveredIndex < 0)
		hoveredIndex = 0;
	if (hoveredIndex > member.items.size() - 1)
		hoveredIndex = member.items.size() - 1;
	if (temp != hoveredIndex)
		fresh();
}